﻿/*
 * 作者：新生命开发团队（http://www.newlifex.com/）
 * 
 * 版权：版权所有 (C) 新生命开发团队 2002-2014
 * 
 * 修改：海洋饼干（cuteant@outlook.com）
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using CuteAnt.Log;
using CuteAnt.Reflection;

namespace CuteAnt.Serialization
{
	/// <summary>读取器基类</summary>
	/// <remarks>
	/// 序列化框架的核心思想：基本类型直接读取，自定义类型反射得到成员，逐层递归读取！详见<see cref="IReaderWriter"/>
	///
	/// 序列化框架的处理顺序为：<see cref="IAccessor" />接口 => <see cref="OnObjectReading" />事件 => 扩展类型 => <see cref="ReadValue(Type,ref Object)" />基础类型 => <see cref="ReadDictionary(Type,ref Object)" />字典 => <see cref="ReadEnumerable(Type,ref Object)" />枚举 => <see cref="ReadSerializable" />序列化接口 => <see cref="ReadCustomObject" />自定义对象 => <see cref="ReadUnKnown" />未知类型 => <see cref="OnObjectReaded" />事件
	///
	/// 反序列化对象时只能调用<see cref="ReadObject(Type)" />方法，其它所有方法（包括所有Read重载）仅用于内部读取或者自定义序列化时使用。
	/// </remarks>
	/// <typeparam name="TSettings">设置类</typeparam>
	public abstract class ReaderBase<TSettings> : ReaderWriterBase<TSettings>, IReader2 where TSettings : ReaderWriterSetting, new()
	{
		#region 基元类型

		#region 字节

		/// <summary>从当前流中读取下一个字节，并使流的当前位置提升 1 个字节。</summary>
		/// <returns></returns>
		public abstract byte ReadByte();

		/// <summary>从当前流中将 count 个字节读入字节数组，如果count小于0，则先读取字节数组长度。</summary>
		/// <param name="count">要读取的字节数。</param>
		/// <returns></returns>
		public virtual byte[] ReadBytes(int count)
		{
			if (count < 0) count = ReadSize();

			if (count <= 0) return null;

			Byte[] buffer = new Byte[count];
			for (int i = 0; i < count; i++)
			{
				buffer[i] = ReadByte();
			}

			return buffer;
		}

		/// <summary>从此流中读取一个有符号字节，并使流的当前位置提升 1 个字节。</summary>
		/// <returns></returns>
		//[CLSCompliant(false)]
		public virtual sbyte ReadSByte()
		{
			return (SByte)ReadByte();
		}

		#endregion

		#region 有符号整数

		/// <summary>读取整数的字节数组，某些写入器（如二进制写入器）可能需要改变字节顺序</summary>
		/// <param name="count">数量</param>
		/// <returns></returns>
		protected virtual Byte[] ReadIntBytes(Int32 count)
		{
			return ReadBytes(count);
		}

		/// <summary>从当前流中读取 2 字节有符号整数，并使流的当前位置提升 2 个字节。</summary>
		/// <returns></returns>
		public virtual short ReadInt16()
		{
			return BitConverter.ToInt16(ReadIntBytes(2), 0);
		}

		/// <summary>从当前流中读取 4 字节有符号整数，并使流的当前位置提升 4 个字节。</summary>
		/// <returns></returns>
		public virtual int ReadInt32()
		{
			return BitConverter.ToInt32(ReadIntBytes(4), 0);
		}

		/// <summary>从当前流中读取 8 字节有符号整数，并使流的当前位置向前移动 8 个字节。</summary>
		/// <returns></returns>
		public virtual long ReadInt64()
		{
			return BitConverter.ToInt64(ReadIntBytes(8), 0);
		}

		#endregion

		#region 无符号整数

		/// <summary>使用 Little-Endian 编码从当前流中读取 2 字节无符号整数，并将流的位置提升 2 个字节。</summary>
		/// <returns></returns>
		//[CLSCompliant(false)]
		public virtual ushort ReadUInt16()
		{
			return (UInt16)ReadInt16();
		}

		/// <summary>从当前流中读取 4 字节无符号整数并使流的当前位置提升 4 个字节。</summary>
		/// <returns></returns>
		//[CLSCompliant(false)]
		public virtual uint ReadUInt32()
		{
			return (UInt32)ReadInt32();
		}

		/// <summary>从当前流中读取 8 字节无符号整数并使流的当前位置提升 8 个字节。</summary>
		/// <returns></returns>
		//[CLSCompliant(false)]
		public virtual ulong ReadUInt64()
		{
			return (UInt64)ReadInt64();
		}

		#endregion

		#region 浮点数

		/// <summary>从当前流中读取 4 字节浮点值，并使流的当前位置提升 4 个字节。</summary>
		/// <returns></returns>
		public virtual float ReadSingle()
		{
			return BitConverter.ToSingle(ReadBytes(4), 0);
		}

		/// <summary>从当前流中读取 8 字节浮点值，并使流的当前位置提升 8 个字节。</summary>
		/// <returns></returns>
		public virtual double ReadDouble()
		{
			return BitConverter.ToDouble(ReadBytes(8), 0);
		}

		#endregion

		#region 字符串

		/// <summary>从当前流中读取下一个字符，并根据所使用的 Encoding 和从流中读取的特定字符，提升流的当前位置。</summary>
		/// <returns></returns>
		public virtual char ReadChar()
		{
			return Convert.ToChar(ReadByte());
		}

		/// <summary>从当前流中读取 count 个字符，以字符数组的形式返回数据，并根据所使用的 Encoding 和从流中读取的特定字符，提升当前位置。</summary>
		/// <param name="count">要读取的字符数。</param>
		/// <returns></returns>
		public virtual char[] ReadChars(int count)
		{
			if (count < 0) count = ReadSize();

			//// count个字符可能的最大字节数
			//var max = Settings.Encoding.GetMaxByteCount(count);

			// 首先按最小值读取
			var data = ReadBytes(count);

			return Settings.Encoding.GetChars(data);

			//// 相同，最简单的一种
			//if (max == count) return Settings.Encoding.GetChars(data);

			//// 按最大值准备一个字节数组
			//Byte[] buffer = new Byte[max];
			//// 复制过去
			//Buffer.BlockCopy(data, 0, buffer, 0, data.Length);

			//// 遍历，以下算法性能较差，将来可以考虑优化
			//Int32 i = 0;
			//for (i = count; i < max; i++)
			//{
			//    Int32 n = Settings.Encoding.GetCharCount(buffer, 0, i);
			//    if (n >= count) break;

			//    buffer[i] = ReadByte();
			//}

			//return Settings.Encoding.GetChars(buffer, 0, i);
		}

		/// <summary>从当前流中读取一个字符串。字符串有长度前缀，一次 7 位地被编码为整数。</summary>
		/// <returns></returns>
		public virtual string ReadString()
		{
			// 先读长度
			Int32 n = ReadSize();
			if (n < 0) return null;
			if (n == 0) return String.Empty;

			Byte[] buffer = ReadBytes(n);

			return Settings.Encoding.GetString(buffer);
		}

		#endregion

		#region 其它

		/// <summary>从当前流中读取 Boolean 值，并使该流的当前位置提升 1 个字节。</summary>
		/// <returns></returns>
		public virtual bool ReadBoolean()
		{
			return ReadByte() != 0;
		}

		/// <summary>从当前流中读取十进制数值，并将该流的当前位置提升十六个字节。</summary>
		/// <returns></returns>
		public virtual decimal ReadDecimal()
		{
			Int32[] data = new Int32[4];
			for (int i = 0; i < data.Length; i++)
			{
				data[i] = ReadInt32();
			}
			return new Decimal(data);
		}

		/// <summary>读取一个时间日期</summary>
		/// <returns></returns>
		public virtual DateTime ReadDateTime()
		{
			return Settings.ConvertInt64ToDateTime(ReadInt64());
		}

		#endregion

		#endregion

		#region 值类型

		/// <summary>读取值类型数据</summary>
		/// <param name="type">类型</param>
		/// <returns></returns>
		public Object ReadValue(Type type)
		{
			Object value = null;
			return ReadValue(type, ref value) ? value : null;
		}

		/// <summary>尝试读取值类型数据，返回是否读取成功</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <returns></returns>
		public virtual Boolean ReadValue(Type type, ref Object value)
		{
			if (type == null)
			{
				if (value == null) return false;
				type = value.GetType();
			}

			var code = Type.GetTypeCode(type);
			switch (code)
			{
				case TypeCode.Boolean:
					value = ReadBoolean();
					return true;
				case TypeCode.Byte:
					value = ReadByte();
					return true;
				case TypeCode.Char:
					value = ReadChar();
					return true;
				case TypeCode.DBNull:
					value = ReadByte();
					return true;
				case TypeCode.DateTime:
					value = ReadDateTime();
					return true;
				case TypeCode.Decimal:
					value = ReadDecimal();
					return true;
				case TypeCode.Double:
					value = ReadDouble();
					return true;
				case TypeCode.Empty:
					value = ReadByte();
					return true;
				case TypeCode.Int16:
					value = ReadInt16();
					return true;
				case TypeCode.Int32:
					value = ReadInt32();
					return true;
				case TypeCode.Int64:
					value = ReadInt64();
					return true;
				case TypeCode.Object:
					break;

				case TypeCode.SByte:
					value = ReadSByte();
					return true;
				case TypeCode.Single:
					value = ReadSingle();
					return true;
				case TypeCode.String:
					value = ReadString();
					return true;
				case TypeCode.UInt16:
					value = ReadUInt16();
					return true;
				case TypeCode.UInt32:
					value = ReadUInt32();
					return true;
				case TypeCode.UInt64:
					value = ReadUInt64();
					return true;
				default:
					break;
			}

			if (type == typeof(Guid))
			{
				value = ReadGuid();
				return true;
			}

			return false;
		}

		/// <summary>读取Guid</summary>
		/// <returns></returns>
		public virtual Guid ReadGuid()
		{
			return new Guid(ReadBytes(16));
		}

		#endregion

		#region 字典

		/// <summary>尝试读取字典类型对象</summary>
		/// <param name="type">类型</param>
		/// <param name="value">对象</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadDictionary(Type type, ref Object value)
		{
			return ReadDictionary(type, ref value, ReadMember);
		}

		/// <summary>尝试读取字典类型对象</summary>
		/// <param name="type">类型</param>
		/// <param name="value">对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadDictionary(Type type, ref Object value, ReadObjectCallback callback)
		{
			if (!typeof(IDictionary).IsAssignableFrom(type)) return false;

			// 计算元素类型
			Type keyType = null;
			Type valueType = null;

			// 无法取得键值类型
			//if (!GetDictionaryEntryType(type, ref keyType, ref valueType)) return false;
			GetDictionaryEntryType(type, ref keyType, ref valueType);

			// 提前创建对象，因为对象引用可能用到
			var index = objRefIndex;
			if (index > 0 && Settings.UseObjRef && value == null)
			{
				value = type.CreateInstance();
				if (value != null) AddObjRef(index, value);
			}

			// 读取键值对集合
			var list = ReadDictionary(keyType, valueType, ReadSize(), callback);
			if (list == null)
			{
				value = null;

				// 结果为空，重新把对象引用设为空。不用担心里面里面已经引用了有对象的对象引用，因为既然列表返回空，表明里面没有元素
				if (index > 0 && Settings.UseObjRef) AddObjRef(index, value);

				return true;
			}

			if (value == null) value = type.CreateInstance();

			var dic = value as IDictionary;
			foreach (var item in list)
			{
				dic.Add(item.Key, item.Value);
			}

			return true;
		}

		/// <summary>读取字典项集合，以读取键值失败作为读完字典项的标识，子类可以重载实现以字典项数量来读取</summary>
		/// <param name="keyType">键类型</param>
		/// <param name="valueType">值类型</param>
		/// <param name="count">元素个数</param>
		/// <param name="callback">处理元素的方法</param>
		/// <returns>字典项集合</returns>
		protected virtual IEnumerable<DictionaryEntry> ReadDictionary(Type keyType, Type valueType, Int32 count, ReadObjectCallback callback)
		{
			var list = new List<DictionaryEntry>();

			// 元素个数小于0，可能是因为不支持元素个数，直接设为最大值
			if (count < 0) count = Int32.MaxValue;
			for (int i = 0; i < count; i++)
			{
				// 一旦有一个元素读不到，就中断
				DictionaryEntry obj;
				Depth++;
				if (!ReadDictionaryEntry(keyType, valueType, ref obj, i, callback))
				{
					Depth--;
					break;
				}
				Depth--;
				list.Add(obj);
			}

			return list;
		}

		/// <summary>读取字典项</summary>
		/// <param name="keyType">键类型</param>
		/// <param name="valueType">值类型</param>
		/// <param name="value">字典项</param>
		/// <param name="index">元素序号</param>
		/// <param name="callback">处理元素的方法</param>
		/// <returns>是否读取成功</returns>
		protected virtual Boolean ReadDictionaryEntry(Type keyType, Type valueType, ref DictionaryEntry value, Int32 index, ReadObjectCallback callback)
		{
			Object key = null;
			Object val = null;

			if (!ReadObject(keyType, ref key)) return false;

			if (!ReadObject(valueType, ref val)) return false;

			value.Key = key;
			value.Value = val;

			return true;
		}

		/// <summary>取得字典的键值类型，默认只支持获取两个泛型参数的字典的键值类型</summary>
		/// <param name="type">字典类型</param>
		/// <param name="keyType">键类型</param>
		/// <param name="valueType">值类型</param>
		/// <returns>是否获取成功，如果失败，则字典读取失败</returns>
		protected virtual Boolean GetDictionaryEntryType(Type type, ref Type keyType, ref Type valueType)
		{
			// 两个泛型参数的泛型
			if (type.IsGenericType)
			{
				var ts = type.GetGenericArguments();
				if (ts != null && ts.Length == 2)
				{
					keyType = ts[0];
					valueType = ts[1];

					return true;
				}
			}

			return false;
		}

		#endregion

		#region 枚举

		/// <summary>尝试读取枚举</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadEnumerable(Type type, ref Object value)
		{
			return ReadEnumerable(type, ref value, ReadMember);
		}

		/// <summary>尝试读取枚举</summary>
		/// <remarks>重点和难点在于如果得知枚举元素类型，这里假设所有元素类型一致，否则实在无法处理</remarks>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadEnumerable(Type type, ref Object value, ReadObjectCallback callback)
		{
			// lengths放在前面读取，主要是xml序列化时，lengths是写在父节点内的属性
			String lengths = null;
			if (type.IsArray && type.GetArrayRank() > 1) lengths = ReadLengths();

			type = CheckAndReadType("ReadEnumerableType", type, value);

			if (!typeof(IEnumerable).IsAssignableFrom(type)) return false;

			// 计算元素类型，如果无法计算，这里不能处理，否则能写不能读（因为不知道元素类型）
			var elementType = type.GetElementTypeEx();

			// 找不到元素类型
			if (elementType == null) throw new SerializationException("无法找到" + type.FullName + "的元素类型！");

			if (!ReadEnumerable(type, elementType, ref value, callback)) return false;

			if (type.IsArray && type.GetArrayRank() > 1)
			{
				if (lengths.IsNullOrWhiteSpace()) return false;
				var strs = lengths.Split(',');
				var param = new Int32[strs.Length];
				for (int i = 0; i < strs.Length; i++)
				{
					param[i] = Convert.ToInt32(strs[i]);
				}

				var array = Array.CreateInstance(type.GetElementType(), param);

				var sub = value as Array;
				foreach (var item in sub)
				{
					ArrEnum(array, ix => array.SetValue(item, ix), item);
				}
				if (array.Length > 0) value = array;
			}

			return true;
		}

		/// <summary>尝试读取枚举</summary>
		/// <remarks>重点和难点在于如果得知枚举元素类型，这里假设所有元素类型一致，否则实在无法处理</remarks>
		/// <param name="type">类型</param>
		/// <param name="elementType">元素类型数组</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadEnumerable(Type type, Type elementType, ref Object value, ReadObjectCallback callback)
		{
			if (!typeof(IEnumerable).IsAssignableFrom(type)) return false;

			var count = ReadSize();

			// 提前创建对象，因为对象引用可能用到
			var index = objRefIndex;
			if (index > 0 && Settings.UseObjRef && value == null)
			{
				if (type.IsArray && type.HasElementType && type.GetElementType() == elementType)
				{
					// 如果是数组，在不知道元素个数时，不处理
					if (count > 0)
					{
						var arr = type.CreateInstance(count) as Array;
						value = arr;
						if (value != null) AddObjRef(index, value);
					}
				}
				else
				{
					value = type.CreateInstance();
					if (value != null) AddObjRef(index, value);
				}
			}

			var list = ReadItems(type, elementType, count, callback);
			if (list == null)
			{
				value = null;

				// 结果为空，重新把对象引用设为空。不用担心里面里面已经引用了有对象的对象引用，因为既然列表返回空，表明里面没有元素
				if (index > 0 && Settings.UseObjRef) AddObjRef(index, value);

				return true;
			}

			if (ProcessItems(type, elementType, ref value, list)) return true;

			// 无法处理
			//WriteLog("ReadEnumerable", String.Format("已完成{1}元素列表的读取，但无法写入到{0}的枚举对象中", type, elementType));
			HmTrace.WriteWarn("已完成{1}元素列表的读取，但无法写入到{0}的枚举对象中", type, elementType);

			return false;
		}

		/// <summary>读取元素集合</summary>
		/// <param name="type">类型</param>
		/// <param name="elementType"></param>
		/// <param name="count">元素个数</param>
		/// <param name="callback">处理元素的方法</param>
		/// <returns></returns>
		protected virtual IList ReadItems(Type type, Type elementType, Int32 count, ReadObjectCallback callback)
		{
			//ArrayList list = new ArrayList();
			var listType = typeof(List<>).MakeGenericType(elementType);
			var list = listType.CreateInstance() as IList;

			// 元素个数小于0，可能是因为不支持元素个数，直接设为最大值
			if (count < 0) count = Int32.MaxValue;
			for (int i = 0; i < count; i++)
			{
				// 一旦有一个元素读不到，就中断
				Object obj = null;
				Depth++;
				if (!ReadItem(elementType, ref obj, i, callback))
				{
					Depth--;

					// 如果不为空，还是加上吧，因为可能读取了一半
					if (obj != null) list.Add(obj);
					break;
				}
				Depth--;
				list.Add(obj);
			}

			return list;
		}

		/// <summary>读取项</summary>
		/// <param name="type">类型</param>
		/// <param name="value">数值</param>
		/// <param name="index">元素序号</param>
		/// <param name="callback">处理元素的方法</param>
		/// <returns></returns>
		protected virtual Boolean ReadItem(Type type, ref Object value, Int32 index, ReadObjectCallback callback)
		{
			return ReadObject(type, ref value, callback);
		}

		/// <summary>处理结果集</summary>
		/// <param name="type">类型</param>
		/// <param name="elementType"></param>
		/// <param name="value">数值</param>
		/// <param name="items"></param>
		/// <returns></returns>
		protected Boolean ProcessItems(Type type, Type elementType, ref Object value, IList items)
		{
			if (type == items.GetType())
			{
				value = items;
				return true;
			}

			// 添加方法
			MethodBase method = null;

			#region 如果源对象不为空，则尽量使用源对象

			if (value != null)
			{
				if (type.IsArray)
				{
					var arr = value as Array;
					if (arr != null)
					{
						//if (HmTrace.Debug && arr.Length != items.Count) throw new XSerializationException(null, "数组元素个数不匹配！");

						for (int i = 0; i < arr.Length && i < items.Count; i++)
						{
							arr.SetValue(items[i], i);
						}
						return true;
					}
				}

				if (typeof(IList).IsAssignableFrom(type))
				{
					var list = value as IList;
					if (list != null)
					{
						foreach (Object item in items)
						{
							list.Add(item);
						}
						return true;
					}
				}
			}

			#endregion

			#region 数组

			if (type.IsArray && type.HasElementType && type.GetElementType() == elementType)
			{
				var arr = type.CreateInstance(items.Count) as Array;
				items.CopyTo(arr, 0);
				value = arr;
				return true;
			}

			#endregion

			#region 检查类型是否有指定类型的构造函数，如果有，直接创建类型，并把数组作为构造函数传入

			var ci = type.GetConstructor(new Type[] { typeof(IEnumerable) });
			if (ci != null)
			{
				value = Reflect.Invoke(null, ci, items);
				return true;
			}

			#endregion

			#region 检查是否实现IEnumerable<>接口，如果不是，转为该接口，后面的构造函数需要用

			var enumType = typeof(IEnumerable<>).MakeGenericType(elementType);

			// 如果数据不是IEnumerable<>类型，则需要转换
			if (!enumType.IsAssignableFrom(items.GetType()))
			{
				// 用List<>来转换
				var listType = typeof(List<>).MakeGenericType(elementType);
				var list = listType.CreateInstance() as IList;
				if (list != null)
				{
					foreach (var item in items)
					{
						list.Add(item);
					}

					if (type == listType)
					{
						value = list;
						return true;
					}

					items = list;
				}
			}

			#endregion

			#region 泛型枚举接口IEnumerable<>的构造函数

			//ci = ConstructorInfoX.Create(type, new Type[] { enumType });
			ci = type.GetConstructor(new Type[] { enumType });
			if (ci != null)
			{
				//value = ci.CreateInstance(items);
				value = Reflect.Invoke(null, ci, items);
				return true;
			}

			#endregion

			#region 是否具有Add方法

			//if (method == null) method = MethodInfoX.Create(type, "Add", new Type[] { elementType });
			//if (method == null) method = Reflect.GetMethod(type, "Add");
			if (method == null) method = type.GetMethodEx("Add");
			if (method != null)
			{
				if (value == null) value = type.CreateInstance();
				foreach (var item in items)
				{
					//method.Invoke(value, item);
					value.Invoke(method, item);
				}
				return true;
			}

			//method = MethodInfoX.Create(type, "AddRange", new Type[] { typeof(ICollection) });
			//if (method == null) method = MethodInfoX.Create(type, "AddRange", new Type[] { typeof(IList) });
			//method = Reflect.GetMethodEx(type, "AddRange", typeof(ICollection));
			//if (method == null) method = Reflect.GetMethodEx(type, "AddRange", typeof(IList));
			method = type.GetMethodEx("AddRange", typeof(ICollection));
			if (method == null) method = type.GetMethodEx("AddRange", typeof(IList));
			if (method != null)
			{
				//method.Invoke(value, items);
				value.Invoke(method, items);

				return true;
			}

			#endregion

			return false;
		}

		#endregion

		#region 序列化接口

		/// <summary>读取实现了可序列化接口的对象</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadSerializable(Type type, ref Object value, ReadObjectCallback callback)
		{
			if (!typeof(ISerializable).IsAssignableFrom(type)) return false;

			WriteLog("ReadSerializable", type.Name);

			var mis = GetMembers(type, value);
			if (mis == null || mis.Length < 1) return true;

			// 调试输出成员列表
			if (Debug) ShowMembers("ReadSerializable", mis);

			for (int i = 0; i < mis.Length; i++)
			{
				Depth++;

				var member = GetMemberBeforeRead(type, value, mis, i);

				// 没有可读成员
				if (member == null) continue;

				WriteLog("ReadMember", member.Name, member.Type.Name);

				if (!ReadMember(member.Type, ref value, member, i, callback)) return false;
				Depth--;
			}

			// 如果为空，实例化并赋值。
			if (value == null)
			{
				var info = new SerializationInfo(type, new FormatterConverter());
				foreach (var item in mis)
				{
					info.AddValue(item.Name, item[value], item.Type);
				}

				value = type.CreateInstance(info, ObjectInfo.DefaultStreamingContext);

				if (value != null) AddObjRef(objRefIndex, value);
			}

			return true;
		}

		#endregion

		#region 未知对象

		/// <summary>读取未知对象（其它所有方法都无法识别的对象），采用BinaryFormatter或者XmlSerialization</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadUnKnown(Type type, ref Object value, ReadObjectCallback callback)
		{
			WriteLog("ReadBinaryFormatter", type.Name);

			// 调用.Net的二进制序列化来解决剩下的事情
			var bf = new BinaryFormatter();
			var ms = new MemoryStream(ReadBytes(-1));
			value = bf.Deserialize(ms);

			return true;
		}

		#endregion

		#region 扩展处理类型

		/// <summary>扩展读取，反射查找合适的读取方法</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <returns></returns>
		public Boolean ReadExtend(Type type, ref Object value)
		{
			if (type == typeof(Byte[]))
			{
				value = ReadBytes(-1);
				return true;
			}
			if (type == typeof(Char[]))
			{
				value = ReadChars(-1);
				return true;
			}

			//if (type == typeof(Guid))
			//{
			//    value = OnReadGuid();
			//    return true;
			//}
			if (type == typeof(IPAddress))
			{
				value = OnReadIPAddress();
				return true;
			}
			if (type == typeof(IPEndPoint))
			{
				value = OnReadIPEndPoint();
				return true;
			}
			if (typeof(Type).IsAssignableFrom(type))
			{
				value = OnReadType();
				return true;
			}

			return false;
		}

		/// <summary>读取IPAddress</summary>
		/// <returns></returns>
		public virtual IPAddress ReadIPAddress()
		{
			return ReadObjRef<IPAddress>(OnReadIPAddress);
		}

		/// <summary>读取IPAddress</summary>
		/// <returns></returns>
		protected virtual IPAddress OnReadIPAddress()
		{
			// 考虑到IPv4和IPv6，地址的字节数不是固定的，所以必须先写大小
			// 然后如果为空，写大小0刚好合适
			var buf = ReadBytes(-1);
			if (buf == null || buf.Length < 1) return null;

			return new IPAddress(buf);
		}

		/// <summary>读取IPEndPoint</summary>
		/// <returns></returns>
		public virtual IPEndPoint ReadIPEndPoint()
		{
			return ReadObjRef<IPEndPoint>(OnReadIPEndPoint);
		}

		/// <summary>读取IPEndPoint</summary>
		/// <returns></returns>
		protected virtual IPEndPoint OnReadIPEndPoint()
		{
			var addr = OnReadIPAddress();
			if (addr == null) return null;

			var ep = new IPEndPoint(IPAddress.Any, 0);

			//! 直接调用OnWrite，不写对象引用，将来可能得考虑写对象引用
			ep.Address = addr;
			ep.Port = ReadInt32();
			return ep;
		}

		/// <summary>读取Type</summary>
		/// <returns></returns>
		public Type ReadType()
		{
			Depth++;

			// 分离出去，便于重载，而又能有效利用对象引用
			var type = ReadObjRef<Type>(OnReadType);

			if (type != null) WriteLog("ReadType", type.FullName);

			Depth--;
			return type;
		}

		/// <summary>读取Type</summary>
		/// <returns></returns>
		protected virtual Type OnReadType()
		{
			var typeName = ReadString();
			if (typeName.IsNullOrWhiteSpace()) return null;

			var type = typeName.GetTypeEx(true);
			if (type != null) return type;

			throw new HmExceptionBase("无法找到名为{0}的类型！", typeName);
		}

		/// <summary>检查对象类型与指定写入类型是否一致，若不一致，则先写入类型，以保证读取的时候能够以正确的类型读取。</summary>
		/// <param name="action"></param>
		/// <param name="type">类型</param>
		/// <param name="value">数值</param>
		/// <returns>返回对象实际类型。</returns>
		protected Type CheckAndReadType(String action, Type type, Object value)
		{
			if (!IsExactType(type))
			{
				WriteLog(action);
				var t = ReadObjectType();

				//TODO 可以在Xml和Json测试猜测类型，写入后，删除Type部分，再尝试读取
				if (t == null && type != null) t = GuessType(type);
				type = t;
				WriteLog(action, type.Name);
			}

			return type;
		}

		/// <summary>猜测类型。对于无法读取到对象类型的类型，并且是接口之类的，可以猜测</summary>
		/// <param name="type">类型</param>
		/// <returns></returns>
		private static Type GuessType(Type type)
		{
			if (type.IsInterface || type.IsAbstract)
			{
				// IEnumerable
				if (typeof(IEnumerable).IsAssignableFrom(type))
				{
					if (!type.IsGenericType)
					{
						// IDictionary
						if (type == typeof(IDictionary)) return typeof(Hashtable);

						// IList
						if (type == typeof(IList)) return typeof(ArrayList);

						// IEnumerable
						if (type == typeof(ICollection) || type == typeof(IEnumerable)) return typeof(ArrayList);
					}
					else
					{
						// 处理泛型
						var gt = type.GetGenericTypeDefinition();
						if (gt != null)
						{
							// 处理泛型参数
							var gs = type.GetGenericArguments();

							// IDictionary<,>
							if (type == typeof(IDictionary<,>)) return typeof(Dictionary<,>).MakeGenericType(gs);

							// IList<>
							if (type == typeof(IList<>)) return typeof(List<>).MakeGenericType(gs);

							// IEnumerable<>
							if (type == typeof(ICollection<>) || type == typeof(IEnumerable<>)) typeof(List<>).MakeGenericType(gs);
						}
					}
				}
				return FindFirstExactType(type);
			}

			return type;
		}

		private static Type FindFirstExactType(Type type)
		{
			if (IsExactType(type)) return type;

			return type.GetAllSubclasses().FirstOrDefault(t => IsExactType(t));
		}

		/// <summary>读对象类型</summary>
		/// <returns></returns>
		protected virtual Type ReadObjectType()
		{
			return ReadType();
		}

		#endregion

		#region 复杂对象

		/// <summary>主要入口方法。从数据流中读取指定类型的对象</summary>
		/// <param name="type">类型</param>
		/// <returns>对象</returns>
		public Object ReadObject(Type type)
		{
			Object value = null;

#if !DEBUG
			try
#endif
			{
				//return ReadObject(type, ref value, null) ? value : null;
				// 尽管读取对象出错，但是可能已经读取部分，还是需要准确返回
				ReadObject(type, ref value, null);
				return value;
			}
#if !DEBUG
			catch (XSerializationException)
			{
				throw;
			}
			catch (Exception ex)
			{
				// 如果不是序列化异常，则包括内部异常链
				var se = new XSerializationException(null, "读取对象出错，可能已读取部分，请查看Value属性！" + ex.Message, ex);
				se.Value = value;
				throw se;
			}
#endif
		}

		/// <summary>主要入口方法。从数据流中读取指定类型的对象</summary>
		/// <returns>对象</returns>
		public T ReadObject<T>()
		{
			return (T)ReadObject(typeof(T));
		}

		/// <summary>主要入口方法。尝试读取目标对象指定成员的值，通过委托方法递归处理成员</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <returns>是否读取成功</returns>
		public Boolean ReadObject(Type type, ref Object value)
		{
			return ReadObject(type, ref value, ReadMember);
		}

		/// <summary>尝试读取目标对象指定成员的值，处理基础类型、特殊类型、基础类型数组、特殊类型数组，通过委托方法处理成员</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public Boolean ReadObject(Type type, ref Object value, ReadObjectCallback callback)
		{
			// 检查数据流是否结束
			if (EndOfStream) return false;

			if (type == null && value != null) type = value.GetType();
			if (callback == null) callback = ReadMember;

			// 检查IAcessor接口
			IAccessor accessor = null;
			if (typeof(IAccessor).IsAssignableFrom(type))
			{
				// 如果为空，实例化并赋值。
				if (value == null)
				{
					//CurrentObject = value = type.CreateInstance();
					value = type.CreateInstance();

					if (value != null) AddObjRef(objRefIndex, value);
				}
				accessor = value as IAccessor;
				if (accessor != null && accessor.Read(this)) return true;
			}

			var rs = ReadObjectWithEvent(type, ref value, callback);

			// 检查IAcessor接口
			if (accessor != null) rs = accessor.ReadComplete(this, rs);

			return rs;
		}

		private Boolean ReadObjectWithEvent(Type type, ref Object value, ReadObjectCallback callback)
		{
			// 事件
			ReadObjectEventArgs e = null;
			if (OnObjectReading != null)
			{
				e = new ReadObjectEventArgs(value, type, callback);

				OnObjectReading(this, e);

				// 事件里面有可能改变了参数
				value = e.Value;
				type = e.Type;
				callback = e.Callback;

				// 事件处理器可能已经成功读取对象
				if (e.Success) return true;
			}

			var rs = OnReadObject(type, ref value, callback);

			// 事件
			if (OnObjectReaded != null)
			{
				if (e == null) e = new ReadObjectEventArgs(value, type, callback);
				e.Value = value;
				e.Success = rs;

				OnObjectReaded(this, e);

				// 事件处理器可以影响结果
				value = e.Value;
				rs = e.Success;
			}

			return rs;
		}

		/// <summary>尝试读取目标对象指定成员的值，处理基础类型、特殊类型、基础类型数组、特殊类型数组，通过委托方法处理成员</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		protected virtual Boolean OnReadObject(Type type, ref Object value, ReadObjectCallback callback)
		{
			if (callback == null) callback = ReadMember;

			//! 2011-05-27 17:33
			//! 精确类型，直接写入值
			//! 未知类型，写对象引用，写类型，写对象

			if (IsExactType(type))
			{
				// 基本类型
				if (ReadValue(type, ref value)) return true;

				// 读取对象引用
				var index = 0;
				if (ReadObjRef(type, ref value, out index)) return true;

				objRefIndex = index;

				// 特殊类型
				if (ReadExtend(type, ref value))
				{
					if (value != null) AddObjRef(index, value);
					return true;
				}

				// 读取引用对象
				if (ReadRefObject(type, ref value, callback))
				{
					if (value != null) AddObjRef(index, value);
					return true;
				}

				return false;
			}
			else
			{
				// 读取对象引用
				var index = 0;
				if (ReadObjRef(type, ref value, out index)) return true;

				// 写对象类型时增加缩进，避免写顶级对象类型的对象引用时无法写入（Depth=1的对象是不写对象引用的）
				Depth++;
				type = CheckAndReadType("ReadObjectType", type, value);
				Depth--;

				// 基本类型
				if (ReadValue(type, ref value))
				{
					if (value != null) AddObjRef(index, value);
					return true;
				}

				// 特殊类型
				if (ReadExtend(type, ref value))
				{
					if (value != null) AddObjRef(index, value);
					return true;
				}

				// 读取引用对象
				objRefIndex = index;
				if (ReadRefObject(type, ref value, callback))
				{
					if (value != null) AddObjRef(index, value);
					return true;
				}

				return false;
			}
		}

		/// <summary>尝试读取引用对象</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		protected virtual Boolean ReadRefObject(Type type, ref Object value, ReadObjectCallback callback)
		{
			// 字典
			if (typeof(IDictionary).IsAssignableFrom(type))
			{
				WriteLog("ReadDictionary", type.Name);

				if (ReadDictionary(type, ref value, callback)) return true;
			}

			// 枚举
			if (typeof(IEnumerable).IsAssignableFrom(type))
			{
				WriteLog("ReadEnumerable", type.Name);

				if (ReadEnumerable(type, ref value, callback)) return true;
			}

			// 可序列化接口
			if (ReadSerializable(type, ref value, callback)) return true;

			// 复杂类型，处理对象成员
			var old = CurrentObject;
			CurrentObject = value;
			if (ReadCustomObject(type, ref value, callback))
			{
				CurrentObject = old;
				return true;
			}
			CurrentObject = old;

			// 检查数据流是否结束
			if (EndOfStream) return false;

			return ReadUnKnown(type, ref value, callback);
		}

		#endregion

		#region 对象引用

		/// <summary>读取引用对象的包装，能自动从引用对象集合里面读取，如果不存在，则调用委托读取对象，并加入引用对象集合</summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="func"></param>
		/// <returns></returns>
		private T ReadObjRef<T>(Func<T> func)
		{
			Object obj = null;
			Int32 index = 0;
			if (ReadObjRef(typeof(T), ref obj, out index)) return (T)obj;

			if (func != null)
			{
				obj = func();

				if (obj != null) AddObjRef(index, obj);

				return (T)obj;
			}

			return default(T);
		}

		private List<Object> objRefs = new List<Object>();
		private Int32 objRefIndex = 0;

		/// <summary>读取对象引用。</summary>
		/// <param name="type">类型</param>
		/// <param name="value">对象</param>
		/// <param name="index">引用计数</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadObjRef(Type type, ref Object value, out Int32 index)
		{
			index = 0;
			if (!Settings.UseObjRef) return false;

			// 顶级特殊处理
			if (Depth <= 1)
				index = 1;
			else
				index = OnReadObjRefIndex();

			if (index < 0) return false;

			if (index == 0)
			{
				WriteLog("ReadObjRef", "null", type == null ? "" : type.Name);

				value = null;
				return true;
			}

			//// 如果引用计数刚好是下一个引用对象，说明这是该对象的第一次引用，返回false
			//if (index == objRefs.Count + 1) return false;

			//if (index > objRefs.Count) throw new HmExceptionBase("对象引用错误，无法找到引用计数为" + index + "的对象！");

			// 引用计数等于索引加一
			if (index > objRefs.Count)
			{
				WriteLog("ReadObjRef", index, type == null ? null : type.Name);

				return false;
			}

			value = objRefs[index - 1];

			if (value != null)
				WriteLog("ReadObjRef", index, value.ToString(), value.GetType().Name);
			else
				WriteLog("ReadObjRef", index, "", type == null ? "" : type.Name);

			return true;
		}

		/// <summary>读取对象引用计数</summary>
		/// <returns></returns>
		protected virtual Int32 OnReadObjRefIndex()
		{
			return ReadSize();
		}

		/// <summary>添加对象引用</summary>
		/// <param name="index">引用计数</param>
		/// <param name="value">对象</param>
		protected virtual void AddObjRef(Int32 index, Object value)
		{
			if (!Settings.UseObjRef || index < 1) return;

			//if (value == null) return;

			while (index > objRefs.Count) objRefs.Add(null);

			objRefs[index - 1] = value;
		}

		#endregion

		#region 自定义对象

		/// <summary>尝试读取自定义对象</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public virtual Boolean ReadCustomObject(Type type, ref Object value, ReadObjectCallback callback)
		{
			var mis = GetMembers(type, value);
			if (callback == null) callback = ReadMember;

			// 如果为空，实例化并赋值。
			if (value == null)
			{
				CurrentObject = value = type.CreateInstance();

				if (value != null) AddObjRef(objRefIndex, value);
			}

			if (mis == null || mis.Length < 1) return true;

			// 调试输出成员列表
			if (Debug) ShowMembers("ReadCustomObject", mis);

			for (int i = 0; i < mis.Length; i++)
			{
				Depth++;

				var member = GetMemberBeforeRead(type, value, mis, i);

				// 没有可读成员
				if (member == null) continue;

				// 基础类型输出日志时，同时输出值，更直观
				if (Type.GetTypeCode(mis[i].Type) == TypeCode.Object)
					WriteLog("ReadMember", member.Name, member.Type.Name);

				var old = CurrentMember;
				CurrentMember = member;

				if (!ReadMember(member.Type, ref value, member, i, callback))
				{
					CurrentMember = old;
					return false;
				}

				CurrentMember = old;

				// 基础类型输出日志时，同时输出值，更直观
				if (Type.GetTypeCode(mis[i].Type) != TypeCode.Object)
					WriteLog("ReadMember", member.Name, member.Type.Name, mis[i][value]);

				Depth--;
			}

			return true;
		}

		/// <summary>读取成员之前获取要读取的成员，默认是index处的成员。</summary>
		/// <remarks>实现者可以重载，改变当前要读取的成员，如果当前成员不在数组里面，则实现者自己跳到下一个可读成员</remarks>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="members">可匹配成员数组</param>
		/// <param name="index">索引</param>
		/// <returns></returns>
		protected virtual IObjectMemberInfo GetMemberBeforeRead(Type type, Object value, IObjectMemberInfo[] members, Int32 index)
		{
			return members[index];
		}

		/// <summary>根据名称，从成员数组中查找成员</summary>
		/// <param name="members">可匹配成员数组</param>
		/// <param name="name">名称</param>
		/// <returns></returns>
		protected IObjectMemberInfo GetMemberByName(IObjectMemberInfo[] members, String name)
		{
			foreach (var item in members)
			{
				if (item.Name == name) return item;
			}

			return null;
		}

		/// <summary>读取对象成员</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="member">成员</param>
		/// <param name="index">成员索引</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		public Boolean ReadMember(Type type, ref Object value, IObjectMemberInfo member, Int32 index, ReadObjectCallback callback)
		{
			if (callback == null) callback = ReadMember;

			// 读取成员前
			ReadMemberEventArgs e = null;
			if (OnMemberReading != null)
			{
				e = new ReadMemberEventArgs(value, type, member, index, callback);

				OnMemberReading(this, e);

				// 事件里面有可能改变了参数
				value = e.Value;
				type = e.Type;
				member = e.Member;
				index = e.Index;
				callback = e.Callback;

				// 事件处理器可能已经成功读取对象
				if (e.Success) return true;
			}

			Object obj = null;
			var rs = OnReadMember(type, ref obj, member, index, callback);

			// 读取成员后
			if (OnMemberReaded != null)
			{
				if (e == null) e = new ReadMemberEventArgs(value, type, member, index, callback);
				e.Value = obj;
				e.Success = rs;

				OnMemberReaded(this, e);

				// 事件处理器可以影响结果
				obj = e.Value;
				rs = e.Success;
			}

			// 设置成员的值
			member[value] = obj;

			return rs;
		}

		/// <summary>读取对象成员</summary>
		/// <param name="type">要读取的对象类型</param>
		/// <param name="value">要读取的对象</param>
		/// <param name="member">成员</param>
		/// <param name="index">成员索引</param>
		/// <param name="callback">处理成员的方法</param>
		/// <returns>是否读取成功</returns>
		protected virtual Boolean OnReadMember(Type type, ref Object value, IObjectMemberInfo member, Int32 index, ReadObjectCallback callback)
		{
			return callback(this, type, ref value, callback);
		}

		private static Boolean ReadMember(IReader reader, Type type, ref Object value, ReadObjectCallback callback)
		{
			return reader.ReadObject(type, ref value, callback);
		}

		#endregion

		#region 事件

		/// <summary>读对象前触发。</summary>
		public event EventHandler<ReadObjectEventArgs> OnObjectReading;

		/// <summary>读对象后触发。</summary>
		public event EventHandler<ReadObjectEventArgs> OnObjectReaded;

		/// <summary>读成员前触发。</summary>
		public event EventHandler<ReadMemberEventArgs> OnMemberReading;

		/// <summary>读成员后触发。</summary>
		public event EventHandler<ReadMemberEventArgs> OnMemberReaded;

		#endregion

		#region 方法

		/// <summary>读取大小</summary>
		/// <returns></returns>
		public Int32 ReadSize()
		{
			if (!UseSize) return -1;

			var size = OnReadSize();

			WriteLog("ReadSize", size);

			return size;
		}

		/// <summary>读取大小</summary>
		/// <returns></returns>
		protected virtual Int32 OnReadSize()
		{
			switch (Settings.SizeFormat)
			{
				case TypeCode.Int16:
				case TypeCode.UInt16:
					return ReadInt16();
				case TypeCode.Int32:
				case TypeCode.UInt32:
				case TypeCode.Int64:
				case TypeCode.UInt64:
				default:
					return ReadInt32();
			}
		}

		/// <summary>读取多维数组相关参数</summary>
		/// <returns></returns>
		protected virtual String ReadLengths()
		{
			var lengths = ReadString();
			WriteLog("ReadLengths", lengths);
			return lengths;
		}

		#endregion

		#region 辅助方法

		/// <summary>给多维数组赋值</summary>
		/// <param name="arr"></param>
		/// <param name="func"></param>
		/// <param name="value">数值</param>
		protected void ArrEnum(Array arr, Action<Int32[]> func, Object value)
		{
			var ix = new Int32[arr.Rank];
			var rank = 0;

			for (int i = 0; i < arr.Length; i++)
			{
				// 当前层以下都清零
				for (int j = rank + 1; j < arr.Rank; j++)
				{
					ix[j] = 0;
				}

				// 设置为最底层
				rank = arr.Rank - 1;

				//do something
				//arr.SetValue(i, ix);
				Object val = arr.GetValue(ix);
				if (val == null || (val.Equals(0) && val != value))
				{
					func(ix);
					return;
				}

				// 当前层递加
				ix[rank]++;

				// 如果超过上限，则减少层次
				while (ix[rank] >= arr.GetLength(rank))
				{
					rank--;
					if (rank < 0) break;
					ix[rank]++;
				}
			}
		}

		#endregion

		#region 辅助属性

		/// <summary>获取一个值，该值表示当前的流位置是否在流的末尾。</summary>
		/// <returns>如果当前的流位置在流的末尾，则为 true；否则为 false。</returns>
		public virtual Boolean EndOfStream
		{
			get
			{
				var s = Stream;
				if (s == null) return false;
				return s.Position == s.Length;
			}
		}

		#endregion
	}
}